-
-
Notifications
You must be signed in to change notification settings - Fork 114
Add a web label #883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Add a web label #883
Conversation
|
Nightly build for this pull request:
|
Metadorius
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Gave you some feedback.
Generally though while this approach definitely has it's place, I am not sure if we should do an explicit separate data source manager? My thoughts were more about something like an implicit manager class; different labels could have content URL endpoints specified right in place, and the response will be shared between them by that class (say, if the requests came to the manager in span of half a minute, then give the same data to every subscriber; if something updates the URL -- then all of the consumers of that URL will receive that).
Not fully set on the above, what are your thoughts?
| private List<string> ParseJSONPath(string json, string path) | ||
| { | ||
| try | ||
| { | ||
| var root = Newtonsoft.Json.Linq.JToken.Parse(json); | ||
| var results = new List<string>(); | ||
|
|
||
| var tokens = root.SelectTokens(path); | ||
|
|
||
| if (tokens != null) | ||
| foreach (var token in tokens) | ||
| if (token != null) | ||
| results.Add(token.ToString()); | ||
|
|
||
| return results.Count > 0 ? results : null; | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Logger.Log($"JSONPath error: {ex.Message}"); | ||
| return null; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should happen way earlier at manager stage, and the control should only receive a parsed json and do template substitution, otherwise we're duplicating work.
Also we already use System.Text.Json, I see that it has no support for JSON Path for some reason, maybe this extension to System.Text.Json would do better? https://www.nuget.org/packages/JsonPath.Net Just so we don't introduce two similar libraries.
| public string Template { get; set; } | ||
| public string LoadingText { get; set; } | ||
| public int MaxResults { get; set; } = 0; | ||
| public string FallbackText { get; set; } = "N/A"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing .L10N call
ClientCore/JSONDataSourceManager.cs
Outdated
| private string ConvertIniToJson(string iniContent) | ||
| { | ||
| var iniFile = new IniFile(); | ||
| using (var reader = new StringReader(iniContent)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a constructor in IniFile that takes a stream, no need to parse it by hand, just take a string and make a stream out of it 😄
| var sb = new StringBuilder(); | ||
| sb.Append("{"); | ||
| bool firstSection = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The aforementioned bringing of JSON parsing earlier than that will allow you to construct the programmatic representation via a few foreaches, iterating sections and then keys to set values and greatly simplifying the code 🙂
| if (string.IsNullOrEmpty(value)) | ||
| continue; | ||
|
|
||
| // format: URL,RefreshIntervalSeconds,TimeoutSeconds,Format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL could have commas in it, I think instead should do something like
[DataSourceName]
URL=https://...
RefreshIntervalSeconds=Also I think individual data source parsing should be in the DataSource itself?
| private static JSONDataSourceManager _instance; | ||
| public static JSONDataSourceManager Instance => _instance ??= new JSONDataSourceManager(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a DI container in use, I think you could use that? The codebase haven't fully migrated though, so tell me if you encounter any issues with that
| private readonly string _url; | ||
| private readonly int _refreshIntervalSeconds; | ||
| private readonly int _timeoutSeconds; | ||
| private readonly string _format; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this _format should be either an enum and/or maybe even a tiny simple interface/class with one method that converts input value (stream?) and gives JSON for arbitrary data representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with an interface. So we can decouple some string parsing logic from the UI logic. My recent editing experience on LAN lobby shows that it might waste a huge amount of time to maintain codes if different kinds of logics are not decoupled
| { | ||
| private readonly string _id; | ||
| private readonly string _url; | ||
| private readonly int _refreshIntervalSeconds; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it run even in background or when controls using it is not active?
although I realise now that it will probably complicate the code a lot, so I don't think there's a big need in doing it exactly. but if there is a lot of players that don't go online -- maybe autorefresh isn't something we may want to do? it will strain our servers quite a bit, maybe we should update just when the control is shown for the first time? (or sth in this direction)
|
|
||
| namespace ClientGUI; | ||
|
|
||
| public class XNAClientJSONLabel : XNALabel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps let's name it XNAClientWebLabel, because it's not just JSON anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also maybe it could be good to have it as a descendant of XNALinkLabel? in case the users want to see details
Fix crash when no datasources specified
| public string Template { get; set; } | ||
| public string LoadingText { get; set; } | ||
| public int MaxResults { get; set; } = 0; | ||
| public string FallbackText { get; set; } = "N/A"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"N/A" is short for not applicable, instead of "not available". So I don't think we should not use "N/A" here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's used interchangeably as either of those, so I think it's fine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example in "Docs/INISystem.md" uses ---. I think using --- as the default value is better because it exactly means "nothing" with placeholders. Then we can change the example value to N/A.
This PR adds a label that can query JSON data from a datasource. We can use this for the online player count, for ladder ranking, or news. INI datasources are also supported.
Datasources are specified in
ClientDefinitions.iniLabels then point to a datasource and can query the JSON.
See
INISytem.mdfor more info.Excuse the crappy screenshot.
